home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / program / mkutil21.zip / SRC / UTIL / MAKEDEP.C < prev    next >
C/C++ Source or Header  |  1995-01-23  |  14KB  |  515 lines

  1. /****************************************************************************
  2. *
  3. *                                 makedep
  4. *
  5. *                    Copyright (C) 1994 SciTech Software.
  6. *                            All rights reserved.
  7. *
  8. * Filename:        $RCSfile$
  9. * Version:        $Revision$
  10. *
  11. * Language:        ANSI C
  12. * Environment:    MSDOS
  13. *
  14. * Description:    Program to build a list of makefile dependencies given
  15. *                a list of object files to be built. Will search the standard
  16. *                set of include file directories for the include files,
  17. *                and can be set to ignore all system include files.
  18. *
  19. *                Written specifically for use with the DMAKE program.
  20. *
  21. * $Id$
  22. *
  23. ****************************************************************************/
  24.  
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <string.h>
  28. #include <ctype.h>
  29. #include <dir.h>
  30. #include <dos.h>
  31. #include "getopt.h"
  32.  
  33. #define    MAX_SRC_DIR     20
  34. #define    MAX_INC_DIR        20
  35. #define    MAX_FILES        300
  36. #define    MAX_DEPEND        300
  37. #define    LINESIZE        256
  38. #define    INCLUDE_VAR        "INCLUDE"
  39. #define    ASM_INC            "include"
  40. #define    ASM_INC_LEN        7
  41. #define    C_INC            "#include"
  42. #define    C_INC_LEN        8
  43.  
  44. /*------------------------- Global variables ------------------------------*/
  45.  
  46. char filenames[MAX_FILES][MAXPATH];
  47. int    incnum = 0;
  48. char incdir[MAX_SRC_DIR][MAXPATH];
  49. int srcnum = 1;
  50. char srcdir[MAX_SRC_DIR][MAXPATH] = {""};
  51. int numDepend;
  52. char dependList[MAX_DEPEND][MAXPATH];
  53. char *srcexts[]              = {".c",".cc",".cpp",".cxx",".asm"};
  54. int    type;
  55. bool ignoreSys;
  56. bool relativePaths;
  57. bool debug = false;
  58.  
  59. #define    NUMEXT    (sizeof(srcexts) / sizeof(char*))
  60.  
  61. /* Use a big stack for Borland C++ */
  62.  
  63. #ifdef __TURBOC__
  64. extern unsigned _stklen = 40000;
  65. #endif
  66.  
  67. /*-------------------------- Implementation -------------------------------*/
  68.  
  69. /* Open a file returning true if successful */
  70.  
  71. int openfile(FILE **in,char *filename,char *mode)
  72. {
  73.     if( (*in = fopen(filename,mode) ) == NULL) {
  74.         return false;    /* Open failed                                    */
  75.         }
  76.     else
  77.         return true;    /* Open was successful                            */
  78. }
  79.  
  80. void error(char *msg)
  81. {
  82.     fprintf(stderr,"FATAL: %s\n", msg);
  83.     exit(1);
  84. }
  85.  
  86. void backslash(char *s)
  87. {
  88.     uint pos = strlen(s);
  89.     if (s[pos-1] != '\\') {
  90.         s[pos] = '\\';
  91.         s[pos+1] = '\0';
  92.         }
  93. }
  94.  
  95. char *skipwhite(char *s)
  96. {
  97.     while (*s && isspace(*s))
  98.         s++;
  99.     return *s ? s : NULL;
  100. }
  101.  
  102. char *skiptowhite(char *s)
  103. {
  104.     while (*s && !isspace(*s))
  105.         s++;
  106.     return *s ? s : NULL;
  107. }
  108.  
  109. void readfilenames(char *name,char filenames[MAX_FILES][MAXPATH],
  110.     int *numfiles)
  111. /****************************************************************************
  112. *
  113. * Function:        readfilenames
  114. * Parameters:    name        - Name of file to read filenames from
  115. *                filenames[]    - Array to place filenames in
  116. *                numfiles    - Number of filenames read
  117. *
  118. * Description:    Reads the names of the files to translate from the
  119. *                specified file 'name'. We expect each file name to we
  120. *                a whole word on the line and ignore all whitespace.
  121. *
  122. ****************************************************************************/
  123. {
  124.     char    buf[MAXPATH];
  125.     FILE    *f;
  126.  
  127.     *numfiles = 0;
  128.     if (!openfile(&f,name,"rt")) {
  129.         /* Unable to open the file - simply return 0 for number of files
  130.          * to process
  131.          */
  132.         return;
  133.         }
  134.  
  135.     while (!feof(f) && (fscanf(f," %s ",buf) == 1)) {
  136.         strlwr(buf);
  137.         strcpy(filenames[*numfiles],buf);
  138.         (*numfiles)++;
  139.         }
  140.  
  141.     fclose(f);
  142. }
  143.  
  144. char *readrsp(char *name)
  145. /****************************************************************************
  146. *
  147. * Function:        readrsp
  148. * Parameters:    name    - Name of small response file to load
  149. * Returns:        Pointer to the buffer containing response file data
  150. *
  151. * Description:    Reads a single line response file into the static buffer
  152. *                and returns a pointer to the buffer.
  153. *
  154. ****************************************************************************/
  155. {
  156.     FILE        *f;
  157.     static char    rspbuf[512];
  158.  
  159.     if (!openfile(&f,name,"rt"))
  160.         error("Unable to open response file!\n");
  161.     fgets(rspbuf,512,f);
  162.     fclose(f);
  163.     return rspbuf;
  164. }
  165.  
  166. void help(void)
  167. {
  168.     printf("Usage: makedep [-arsSIu @rspfile] <objects>\n\n");
  169.     printf("where 'objects' is the list of all object files to build the dependency\n");
  170.     printf("information for. You can use @rspfile to obtain the objects file names from\n");
  171.     printf("a response file rather than from the command line. Include files are\n");
  172.     printf("in the current directory or in the directories specified by the INCLUDE\n");
  173.     printf("environment variable.\n");
  174.     printf("\n");
  175.     printf("Options are:\n");
  176.     printf("\n");
  177.     printf("  -a<file> Append the output to the specified file (stdout is default)\n");
  178.     printf("  -r       Generate relative pathnames for dependencies (not system includes)\n");
  179.     printf("  -s       Ignore all system include files (eg: <stdio.h>)\n");
  180.     printf("  -S<dir>  List of directories to search for source files (-S@rsp also valid)\n");
  181.     printf("  -I<inc>  List of directories to search for include files (-I@rsp also valid)\n");
  182.     printf("  -u       Generate dependencies in all uppercase (lowercase is default)\n");
  183.     exit(1);
  184. }
  185.  
  186. int getSrcName(char *srcname,char *dependname)
  187. /****************************************************************************
  188. *
  189. * Function:        getSrcName
  190. * Parameters:    srcname        - Place to store the source file name
  191. *                dependname    - Dependent file name (.obj) being used
  192. * Returns:        0 for C files, 1 for assembler files, -1 if not found.
  193. *
  194. * Description:    Attempts to locate the source file for the specified
  195. *                object file dependency and return the pathname. If one
  196. *                cannot be found we bomb out.
  197. *
  198. ****************************************************************************/
  199. {
  200.     int                i,j;
  201.     char            tmp[MAXPATH],drive[_MAX_DRIVE],dir[_MAX_DIR];
  202.     char            name[_MAX_FNAME],ext[_MAX_EXT];
  203.     struct find_t    f;
  204.  
  205.     _splitpath(dependname,drive,dir,name,ext);
  206.     for (i = 0; i < srcnum; i++) {
  207.         for (j = 0; j < NUMEXT; j++) {
  208.             _makepath(tmp,NULL,srcdir[i],name,srcexts[j]);
  209.             if (debug)
  210.                 fprintf(stderr,"Searching for %s ... \n", tmp);
  211.             if (!_dos_findfirst(tmp,_A_ARCH|_A_RDONLY|_A_HIDDEN,&f)) {
  212.                 strcpy(srcname, tmp);
  213.                 if (debug)
  214.                     fprintf(stderr,"found\n");
  215.                 return (srcexts[j][1] == 'a');
  216.                 }
  217.             if (debug)
  218.                 fprintf(stderr,"not found\n");
  219.             }
  220.         }
  221.     fprintf(stderr,"Unable to locate %s.\n", dependname);
  222.     return -1;
  223. }
  224.  
  225. void addIncName(char *incname,bool sysInclude)
  226. /****************************************************************************
  227. *
  228. * Function:        addIncName
  229. * Parameters:    incname        - Name of include file to add
  230. *                sysInclude    - True if it is a system include file
  231. *
  232. * Description:    Attempts to search for the specified include file and
  233. *                builds the full pathname to it.
  234. *
  235. ****************************************************************************/
  236. {
  237.     int                i,j;
  238.     char            tmp[MAXPATH],cwd[MAXPATH],drive[_MAX_DRIVE];
  239.     char            dir[_MAX_DIR],name[_MAX_FNAME],ext[_MAX_EXT];
  240.     char            cdrive[_MAX_DRIVE],cdir[_MAX_DIR],cname[_MAX_FNAME];
  241.     char            cext[_MAX_EXT],tdir[_MAX_DIR],*p,*cp;
  242.     struct find_t    f;
  243.  
  244.     strlwr(incname);
  245.     for (i = (sysInclude ? 1 : 0); i < incnum; i++) {
  246.         strcpy(tmp,incdir[i]);
  247.         strcat(tmp,incname);
  248.         if (debug)
  249.             fprintf(stderr,"Searching for %s ... \n", tmp);
  250.         if (!_dos_findfirst(tmp,_A_ARCH|_A_RDONLY|_A_HIDDEN,&f)) {
  251.             if (debug)
  252.                 fprintf(stderr,"found\n");
  253.             if (relativePaths && !sysInclude) {
  254.                 _splitpath(tmp,drive,dir,name,ext);
  255.                 getcwd(cwd,MAXPATH);
  256.                 strlwr(cwd);
  257.                 backslash(cwd);
  258.                 _splitpath(cwd,cdrive,cdir,cname,cext);
  259.                 if (drive[0] == cdrive[0]) {
  260.                     p = dir;
  261.                     cp = cdir;
  262.                     /* Skip common directory paths */
  263.                     while (*p && *cp  && (*p == *cp)) {
  264.                         p++; cp++;
  265.                         }
  266.                     /* Skip back to start of uncommon directory name */
  267.                     while (*(p-1) != '\\') {
  268.                         p--;
  269.                         cp--;
  270.                         }
  271.                     strcpy(tdir,p);
  272.                     p = cdir;
  273.                     while ((cp = strchr(cp,'\\')) != NULL) {
  274.                         *p++ = '.';
  275.                         *p++ = '.';
  276.                         *p++ = '\\';
  277.                         cp++;
  278.                         }
  279.                     *p = 0;
  280.                     strcat(cdir,tdir);
  281.                     _makepath(tmp,NULL,cdir,name,ext);
  282.                     }
  283.                 }
  284.             for (j = 0; j < numDepend; j++)
  285.                 if (strcmp(dependList[j],tmp) == 0)
  286.                     return;
  287.             if (numDepend == MAX_DEPEND)
  288.                 error("Too many dependant files!");
  289.             strcpy(dependList[numDepend++],tmp);
  290.             return;
  291.             }
  292.         if (debug)
  293.             fprintf(stderr,"not found\n");
  294.         }
  295.  
  296.     fprintf(stderr,"Unable to locate include file %s.\n", incname);
  297. }
  298.  
  299. void buildDependList(char *srcname)
  300. /****************************************************************************
  301. *
  302. * Function:        buildDependList
  303. * Parameters:    srcname            - Name of source file to build dependencies
  304. *
  305. * Description:    Builds the list of dependencies for the source file.
  306. *
  307. ****************************************************************************/
  308. {
  309.     FILE    *f;
  310.     int        i,first,last,sysInclude;
  311.     char    line[LINESIZE],*s,*e;
  312.  
  313.     if (!openfile(&f,srcname,"rt")) {
  314.         printf("Unable to open source file %s!!", srcname);
  315.         exit(1);
  316.         }
  317.  
  318.     first = numDepend;
  319.     while (fgets(line,LINESIZE,f)) {
  320.         if ((s = skipwhite(line)) == NULL)
  321.             continue;
  322.  
  323.         if (type) {                /* Assembler source file        */
  324.             if (strnicmp(s,ASM_INC,ASM_INC_LEN) == 0) {
  325.                 if ((s = skipwhite(s + ASM_INC_LEN)) == NULL)
  326.                     continue;
  327.                 if (*s == '"')
  328.                     s++;
  329.                 if ((e = skiptowhite(s)) == NULL)
  330.                     continue;
  331.                 if (*(e-1) == '"')
  332.                     e--;
  333.                 *e = 0;
  334.                 addIncName(s,false);
  335.                 }
  336.             }
  337.         else {                    /* C style source file            */
  338.             if (strnicmp(s,C_INC,C_INC_LEN) == 0) {
  339.                 if ((s = skipwhite(s + C_INC_LEN)) == NULL)
  340.                     continue;
  341.                 if (*s == '<') {
  342.                     if (ignoreSys)
  343.                         continue;
  344.                     sysInclude = true;
  345.                     }
  346.                 else sysInclude = false;
  347.                 s++;
  348.                 if ((e = skiptowhite(s)) == NULL)
  349.                     continue;
  350.                 e--;
  351.                 *e = 0;
  352.                 addIncName(s,sysInclude);
  353.                 }
  354.             }
  355.         }
  356.     last = numDepend;
  357.     fclose(f);
  358.  
  359.     /* Recursively parse each include file found */
  360.     if (first < last) {
  361.         for (i = first; i < last; i++)
  362.             buildDependList(dependList[i]);
  363.         }
  364. }
  365.  
  366. void processFiles(FILE *out,char filenames[MAX_FILES][MAXPATH],
  367.     int numfiles,bool uppercase)
  368. /****************************************************************************
  369. *
  370. * Function:        processFiles
  371. * Parameters:    out                - File to send output list to
  372. *               filenames        - List of object file names to process
  373. *               numfiles        - Numer of files to process
  374. *
  375. * Description:    Processes the list of files generating the list of
  376. *                dependencies in the output list.
  377. *
  378. ****************************************************************************/
  379. {
  380.     int        i,j;
  381.     char    srcname[MAXPATH];
  382.  
  383.     for (i = 0; i < numfiles; i++) {
  384.         if ((type = getSrcName(srcname,filenames[i])) == -1)
  385.             continue;
  386.         numDepend = 0;
  387.         buildDependList(srcname);
  388.  
  389.         /* Last one in list is the original source file */
  390.         strcpy(dependList[numDepend++],srcname);
  391.  
  392.         /* Convert to uppercase or lower case as needed */
  393.         if (uppercase) {
  394.             strupr(filenames[i]);
  395.             for (j = 0; j < numDepend; j++)
  396.                 strupr(dependList[j]);
  397.             }
  398.  
  399.         /* Write the list of dependant files to the output file */
  400.         for (j = 0; j < numDepend; j++) {
  401.             fprintf(out, "%s: %s\n", filenames[i],dependList[j]);
  402.             free(dependList[j]);
  403.             }
  404.         }
  405. }
  406.  
  407. int main(int argc,char *argv[])
  408. {
  409.     int        i,numfiles,option;
  410.     char    *argument,*s,*d;
  411.     char    tmp[255];
  412.     FILE    *out = stdout;
  413.     bool    uppercase;
  414.  
  415.     uppercase = ignoreSys = relativePaths = false;
  416.  
  417.     /* Read include file directories from the INCLUDE evironment var */
  418.  
  419.     getcwd(tmp,MAXPATH);
  420.     strlwr(tmp);
  421.     strcpy(incdir[incnum],tmp);
  422.     backslash(incdir[incnum++]);
  423.     if (getenv(INCLUDE_VAR)) {
  424.         strcpy(tmp,getenv(INCLUDE_VAR));
  425.         strlwr(tmp);
  426.         s = tmp;
  427.         while ((d = strchr(s,';')) != NULL) {
  428.             *d++ = '\0';
  429.             strcpy(incdir[incnum],s);
  430.             backslash(incdir[incnum++]);
  431.             s = d;
  432.             }
  433.         strcpy(incdir[incnum],s);
  434.         backslash(incdir[incnum++]);
  435.         }
  436.  
  437.     /* Parse command line options */
  438.     do {
  439.         option = getopt(argc,argv,"a:rsS:I:uD",&argument);
  440.         switch(option) {
  441.             case 'a':
  442.                 if (!openfile(&out,argument,"at"))
  443.                     error("Unable to open output file");
  444.                 break;
  445.             case 'r':    relativePaths = true;        break;
  446.             case 's':    ignoreSys = true;            break;
  447.             case 'u':   uppercase = true;            break;
  448.             case 'D':     debug = true;                 break;
  449.             case 'S':
  450.                 if (argument[0] == '@')
  451.                     argument = readrsp(argument+1);
  452.                 strlwr(argument);
  453.                 s = argument;
  454.                 while ((d = strchr(s,';')) != NULL) {
  455.                     *d++ = '\0';
  456.                     strcpy(srcdir[srcnum],s);
  457.                     backslash(srcdir[srcnum++]);
  458.                     s = d;
  459.                     }
  460.                 strcpy(srcdir[srcnum],s);
  461.                 backslash(srcdir[srcnum++]);
  462.                 break;
  463.             case 'I':
  464.                 if (argument[0] == '@')
  465.                     argument = readrsp(argument+1);
  466.                 strlwr(argument);
  467.                 s = argument;
  468.                 while ((d = strchr(s,';')) != NULL) {
  469.                     *d++ = '\0';
  470.                     strcpy(incdir[incnum],s);
  471.                     backslash(incdir[incnum++]);
  472.                     s = d;
  473.                     }
  474.                 strcpy(incdir[incnum],s);
  475.                 backslash(incdir[incnum++]);
  476.                 break;
  477.             case INVALID:
  478.                 help();
  479.             }
  480.         } while (option != ALLDONE && option != PARAMETER);
  481.  
  482.     if ((argc - nextargv) < 1)
  483.         help();
  484.  
  485.     /* Read list of files to process from command line or from response
  486.      * file.
  487.      */
  488.     if (argv[nextargv][0] == '@')
  489.         readfilenames(&argv[nextargv][1],filenames,&numfiles);
  490.     else {
  491.         numfiles = 0;
  492.         for (i = nextargv; i < argc; i++) {
  493.             strcpy(filenames[numfiles],argv[i]);
  494.             strlwr(filenames[numfiles++]);
  495.             }
  496.         }
  497.  
  498.     if (debug) {
  499.         fprintf(stderr,"Source directories:\n");
  500.         for (i = 0; i < srcnum; i++)
  501.             fprintf(stderr,"%s\n", srcdir[i]);
  502.         fprintf(stderr,"Include directories:\n");
  503.         for (i = 0; i < incnum; i++)
  504.             fprintf(stderr,"%s\n", incdir[i]);
  505.         fprintf(stderr,"Object files:\n");
  506.         for (i = 0; i < numfiles; i++)
  507.             fprintf(stderr,"%s\n", filenames[i]);
  508.         }
  509.     processFiles(out,filenames,numfiles,uppercase);
  510.  
  511.     if (out != stdout)
  512.         fclose(out);
  513.     return 0;
  514. }
  515.